home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
AmigActive 10
/
AACD 10.iso
/
AACD
/
Online
/
SpeakFreely
/
src
/
vatpkt.c
< prev
next >
Wrap
C/C++ Source or Header
|
2000-05-18
|
8KB
|
334 lines
/*
VAT packet interconversion routines
*/
#include "speakfree.h"
#include "vat.h"
#include <pwd.h>
#include <sys/param.h>
static audio_descr_t adt[] = {
/* enc sample ch */
{AE_PCMU, 8000, 1}, /* 0 PCMU */
{AE_MAX, 8000, 1}, /* 1 1016 */
{AE_MAX, 0, 1}, /* 2 G721 32 kb/s CCITT ADPCM */
{AE_GSM, 8000, 1}, /* 3 GSM */
{AE_MAX, 0, 1}, /* 4 G723 24 kb/s CCITT ADPCM */
{AE_MAX, 0, 1}, /* 5 unassigned */
{AE_MAX, 0, 1}, /* 6 unassigned */
{AE_MAX, 0, 1}, /* 7 unassigned */
{AE_MAX, 0, 1}, /* 8 unassigned */
{AE_MAX, 0, 1}, /* 9 unassigned */
{AE_MAX, 0, 1}, /* 10 unassigned */
{AE_MAX, 0, 1}, /* 11 unassigned */
{AE_MAX, 0, 1}, /* 12 unassigned */
{AE_MAX, 0, 1}, /* 13 unassigned */
{AE_MAX, 0, 1}, /* 14 unassigned */
{AE_MAX, 0, 1}, /* 15 unassigned */
{AE_MAX, 0, 1}, /* 16 unassigned */
{AE_MAX, 0, 1}, /* 17 unassigned */
{AE_MAX, 0, 1}, /* 18 unassigned */
{AE_MAX, 0, 1}, /* 19 unassigned */
{AE_MAX, 0, 1}, /* 20 unassigned */
{AE_MAX, 0, 1}, /* 21 unassigned */
{AE_MAX, 0, 1}, /* 22 unassigned */
{AE_MAX, 0, 1}, /* 23 unassigned */
{AE_MAX, 0, 1}, /* 24 unassigned */
{AE_MAX, 0, 1}, /* 25 unassigned */
{AE_MAX, 0, 1}, /* 26 L16, 16000 samples/sec */
{AE_MAX, 0, 1}, /* 27 L16, 44100 samples/sec, 2 channels */
{AE_LPC, 8000, 1}, /* 28 LPC, 4 frames */
{AE_LPC, 8000, 1}, /* 29 LPC, 1 frame */
{AE_IDVI, 8000, 1}, /* 30 32 kb/s Intel DVI ADPCM */
{AE_MAX, 0, 1}, /* 31 unassigned */
};
/* ISVAT -- Determine if this is a parseable VAT format packet.
If so, convert it to an equivalent sound buffer. */
int isvat(pkt, len)
unsigned char *pkt;
int len;
{
int findex = pkt[1] & VATHF_FMTMASK;
soundbuf *s = (soundbuf *) pkt;
/* Validate (as much as possible) whether this is a VAT packet
that we're able to translate. */
if (((pkt[0] & 0xC0) == 0) && ((pkt[1] & 0x60) == 0) /* &&
(adt[findex].encoding != AE_MAX) */
) {
struct soundbuf sb;
unsigned char *payload;
int paylen;
/*fprintf(stderr, "VAT Ver = %d, nsid = %d, ts = %d, format = %d confid = %d, tstamp = %ld\n",
pkt[0] >> 6, pkt[0] & NSID_MASK, !!(pkt[1] & VATHF_NEWTS), findex,
(((unsigned int) pkt[2]) << 8) | pkt[3],
(((unsigned long) pkt[4]) << 24) |
(((unsigned long) pkt[5]) << 16) |
(((unsigned long) pkt[6]) << 8) |
(((unsigned long) pkt[7]) << 0));
*/
payload = pkt + (8 + 4 * (pkt[0] & NSID_MASK)); /* Payload start */
paylen = len - ((8 + 4 * (pkt[0] & NSID_MASK))); /* Payload length */
sb.compression = fProtocol;
sb.buffer.buffer_len = 0;
#ifdef NEEDED
/* Fake a VAT unique host name from the conference identifier. */
sprintf(sb.sendinghost, ".VAT:%02X%02X",
pkt[2], pkt[3]);
#else
strcpy(sb.sendinghost, ".VAT");
#endif
switch (adt[findex].encoding) {
case AE_PCMU:
sb.buffer.buffer_len = paylen;
bcopy(payload, sb.buffer.buffer_val, paylen);
break;
case AE_GSM:
sb.buffer.buffer_len = paylen + sizeof(short);
bcopy(payload, sb.buffer.buffer_val + 2, paylen);
*((short *) sb.buffer.buffer_val) =
htons((short) ((((long) paylen) * 160) / 33));
sb.compression |= fCompGSM;
break;
case AE_IDVI:
bcopy(payload + 4, sb.buffer.buffer_val, paylen - 4);
bcopy(payload, sb.buffer.buffer_val + (paylen - 4), 3);
sb.buffer.buffer_len = paylen - 1;
if (adt[findex].sample_rate == 8000) {
sb.compression |= fCompADPCM;
} else {
#ifdef NEEDED
/* Bogus attempt to convert sampling rate. We
really need to do this in linear mode, which isn't
supported on all SPARCs. This is better than
nothing, though. */
int inc = adt[findex].sample_rate / 8000, i;
unsigned char *in = (unsigned char *) sb.buffer.buffer_val,
*out = (unsigned char *) sb.buffer.buffer_val;
adpcmdecomp(&sb);
for (i = 0; i < (paylen - 4) / inc; i++) {
*out++ = *in;
in += inc;
}
sb.buffer.buffer_len /= inc;
#endif
}
break;
case AE_LPC:
sb.buffer.buffer_len = paylen + sizeof(short);
{ int i;
unsigned char *in = payload,
*out = (unsigned char *) sb.buffer.buffer_val + 2;
for (i = 0; i < paylen / 14; i++) {
bcopy(in, out, 3);
out[3] = 0;
bcopy(in + 3, out + 4, 10);
in += 14;
out += 14;
}
}
*((short *) sb.buffer.buffer_val) =
htons((short) ((((long) paylen) * LPC_FRAME_SIZE) / 14));
sb.compression |= fCompLPC;
break;
case AE_L16:
if (adt[findex].channels == 1) {
int i, j, k;
for (i = j = k = 0; i < (paylen / 8); i++) {
if ((k & 3) != 2 && ((i % 580) != 579)) {
sb.buffer.buffer_val[j++] =
audio_s2u((((unsigned short *) payload)[i * 4]));
}
k = (k + 1) % 11;
}
sb.buffer.buffer_len = j;
} else if (adt[findex].channels == 2) {
int i, j, k;
for (i = j = k = 0; i < (paylen / 16); i++) {
if ((k & 3) != 2 && ((i % 580) != 579)) {
sb.buffer.buffer_val[j++] =
audio_s2u(((((unsigned short *) payload)[i * 8]) +
(((unsigned short *) payload)[i * 8 + 1])) / 2);
}
k = (k + 1) % 11;
}
sb.buffer.buffer_len = j;
}
break;
default:
/* Unknown compression type. */
sb.buffer.buffer_len = 0;
break;
}
bcopy(&sb, pkt, (int) (((sizeof sb - BUFL)) + sb.buffer.buffer_len));
return TRUE;
}
return FALSE;
}
/* VATOUT -- Convert a sound buffer into a VAT packet, given the
timestamp for the next packet sent to this connection. */
int vatout(sb, ssrc_i, timestamp_i, spurt)
soundbuf *sb;
unsigned long ssrc_i;
unsigned long timestamp_i;
int spurt;
{
soundbuf rp;
char *pkt = (char *) &rp;
LONG pl = 0;
pkt[0] = 0;
pkt[1] = spurt ? 0x80 : 0;
pkt[2] = ssrc_i & 0xFF;
pkt[3] = (ssrc_i >> 8) & 0xFF;
*((long *) (pkt + 4)) = htonl(timestamp_i);
if (sb->compression & fCompGSM) {
pkt[1] |= VAT_AUDF_GSM;
bcopy(sb->buffer.buffer_val + 2, pkt + 8,
(int) sb->buffer.buffer_len - 2);
pl = (sb->buffer.buffer_len - 2) + 8;
} else if (sb->compression & fCompADPCM) {
pkt[1] |= VAT_AUDF_IDVI;
bcopy(sb->buffer.buffer_val, pkt + 8 + 4,
(int) sb->buffer.buffer_len - 3);
bcopy(sb->buffer.buffer_val + ((int) sb->buffer.buffer_len - 3),
pkt + 8, 3);
pkt[8 + 3] = 0;
pl = (sb->buffer.buffer_len + 1) + 8;
} else if (sb->compression & fCompLPC) {
int n = (int) ((sb->buffer.buffer_len - 2) / 14);
int i;
char *cp = pkt + 8, *sp = sb->buffer.buffer_val + 2;
pkt[1] |= VAT_AUDF_LPC4;
pl = 8;
for (i = 0; i < n; i++) {
bcopy(sp, cp, 3);
bcopy(sp + 4, cp + 3, 10);
sp += 14;
cp += 14;
pl += 14;
}
} else { /* Uncompressed PCMU samples */
#if (VAT_AUDF_MULAW8 != 0)
pkt[1] |= VAT_AUDF_MULAW8;
#endif
bcopy(sb->buffer.buffer_val, pkt + 8,
(int) sb->buffer.buffer_len);
pl = (int) sb->buffer.buffer_len + 8;
}
if (pl > 0) {
bcopy(pkt, (char *) sb, (int) pl);
}
return pl;
}
/* MAKEVATID -- Create VAT ID packet. */
int makeVATid(vp, ssrc_i)
char **vp;
unsigned long ssrc_i;
{
char *sp = NULL, *cp = NULL;
struct passwd *pw;
char s[256];
int l = 0;
/* Watch as we make increasingly desperate attempts to
obtain the user's full name. */
sp = getenv("SPEAKFREE_ID");
if (sp != NULL && strlen(sp) > 0) {
char *ep = strchr(sp, ':');
if (ep != NULL) {
*ep = 0;
}
}
if (sp == NULL) {
pw = getpwuid(getuid());
if (pw != NULL) {
if (pw->pw_gecos != NULL) {
strcpy(s, pw->pw_gecos);
sp = s;
} else if (pw->pw_name != NULL) {
char hn[MAXHOSTNAMELEN];
hn[0] = 0;
gethostname(hn, sizeof hn);
sprintf(s, "%s@%s", pw->pw_name, hn);
sp = s;
}
}
}
if (sp == NULL) {
if ((sp = getenv("SPEAKFREE_CNAME")) != NULL && strlen(sp) > 0) {
if (sp[0] == '*') {
sp++;
}
}
}
if (sp == NULL) {
sp = "Unknown User";
}
cp = malloc(4 + strlen(sp) + 1);
if (cp != NULL) {
cp[0] = 0;
cp[1] = 1;
cp[2] = ssrc_i & 0xFF;
cp[3] = (ssrc_i >> 8) & 0xFF;
strcpy(cp + 4, sp);
l = 4 + strlen(sp) + 1;
}
*vp = cp;
return l;
}
/* MAKEVATDONE -- Create VAT "DONE" packet. */
int makevatdone(v, ssrc_i)
char *v;
unsigned long ssrc_i;
{
v[0] = 0;
v[1] = 2;
v[2] = ssrc_i & 0xFF;
v[3] = (ssrc_i >> 8) & 0xFF;
return 4;
}